package com.io.nio;

import com.common.utils.ByteBufferUtil;

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.StandardCharsets;

/**
 *
 */
public class ByteBufferDemo1 {

    /**
     *
     * 方法一 字符串与ByteBuffer相互转换
     * 编码：字符串调用getByte方法获得byte数组，将byte数组放入ByteBuffer中
     * 解码：先调用ByteBuffer的flip方法，然后通过StandardCharsets的decoder方法解码
     */
    public void strAndBufferChange1(){
        // 准备两个字符串
        String str1 = "hello";
        String str2 = "";


        ByteBuffer buffer1 = ByteBuffer.allocate(16);
        // 通过字符串的getByte方法获得字节数组，放入缓冲区中
        buffer1.put(str1.getBytes());
        ByteBufferUtil.debugAll(buffer1);

        // 将缓冲区中的数据转化为字符串
        // 切换模式
        buffer1.flip();

        // 通过StandardCharsets解码，获得CharBuffer，再通过toString获得字符串
        str2 = StandardCharsets.UTF_8.decode(buffer1).toString();
        System.out.println(str2);
        ByteBufferUtil.debugAll(buffer1);
    }

    /**
     * 方法二
     * 编码：通过StandardCharsets的encode方法获得ByteBuffer，此时获得的ByteBuffer为读模式，无需通过flip切换模式
     * 解码：通过StandardCharsets的decoder方法解码
     */
    public void strAndBufferChange2(){
            // 准备两个字符串
            String str1 = "hello";
            String str2 = "";

            // 通过StandardCharsets的encode方法获得ByteBuffer
            // 此时获得的ByteBuffer为读模式，无需通过flip切换模式
            ByteBuffer buffer1 = StandardCharsets.UTF_8.encode(str1);
            ByteBufferUtil.debugAll(buffer1);

            // 将缓冲区中的数据转化为字符串
            // 通过StandardCharsets解码，获得CharBuffer，再通过toString获得字符串
            str2 = StandardCharsets.UTF_8.decode(buffer1).toString();
            System.out.println(str2);
            ByteBufferUtil.debugAll(buffer1);
    }

    /**
     * 方法三
     * 编码：字符串调用getByte()方法获得字节数组，将字节数组传给ByteBuffer的wrap()方法，通过该方法获得ByteBuffer。同样无需调用flip方法切换为读模式
     * 解码：通过StandardCharsets的decoder方法解码
     */
    public void strAndBufferChange3(){
        // 准备两个字符串
        String str1 = "hello";
        String str2 = "";

        // 通过StandardCharsets的encode方法获得ByteBuffer
        // 此时获得的ByteBuffer为读模式，无需通过flip切换模式
        ByteBuffer buffer1 = ByteBuffer.wrap(str1.getBytes());
        ByteBufferUtil.debugAll(buffer1);

        // 将缓冲区中的数据转化为字符串
        // 通过StandardCharsets解码，获得CharBuffer，再通过toString获得字符串
        str2 = StandardCharsets.UTF_8.decode(buffer1).toString();
        System.out.println(str2);
        ByteBufferUtil.debugAll(buffer1);
    }

    /**
     * ByteBuffer常用方法
     */
    public void byteMethod(){
        ByteBuffer buffer = ByteBuffer.allocate(10);
        // 向buffer中写入1个字节的数据
        buffer.put((byte)97);
        // 使用工具类，查看buffer状态
        ByteBufferUtil.debugAll(buffer);

        // 向buffer中写入4个字节的数据
        buffer.put(new byte[]{98, 99, 100, 101});
        ByteBufferUtil.debugAll(buffer);

        // 获取数据
        buffer.flip();
        ByteBufferUtil.debugAll(buffer);
        System.out.println(buffer.get());
        System.out.println(buffer.get());
        ByteBufferUtil.debugAll(buffer);

        // 使用compact切换模式
        buffer.compact();
        ByteBufferUtil.debugAll(buffer);

        // 再次写入
        buffer.put((byte)102);
        buffer.put((byte)103);
        ByteBufferUtil.debugAll(buffer);
    }

    /**
     * 使用ByteBuffer读取文件中的内容
     */
    public void readFileChannel(){
        // 获得FileChannel
        try (FileChannel channel = new FileInputStream("stu.txt").getChannel()) {
            // 获得缓冲区
            ByteBuffer buffer = ByteBuffer.allocate(10);
            int hasNext = 0;
            StringBuilder builder = new StringBuilder();
            while((hasNext = channel.read(buffer)) > 0) {
                // 切换模式 limit=position, position=0
                buffer.flip();
                // 当buffer中还有数据时，获取其中的数据
                while(buffer.hasRemaining()) {
                    builder.append((char)buffer.get());
                }
                // 切换模式 position=0, limit=capacity
                buffer.clear();
            }
            System.out.println(builder.toString());
        } catch (IOException e) {

        }
    }
}
